package com.qn.init;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ClassUtil;
import cn.hutool.core.util.ReflectUtil;
import com.qn.common.code.ErrorCode;
import com.qn.common.enums.I18nEnum;
import com.qn.entity.I18nMsg;
import com.qn.service.I18nMsgService;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 初始化错误码
 *
 * @author QN
 * @date 2025/01/03
 */
@Slf4j
@Component
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class InitI18nMsgStartupRunner {

    /**
     * 错误码类名
     */
    public static final String[] ERROR_CODE_CLASS_NAMES = {"GlobalErrorCodeConstants", "ErrorCodeConstants"};
    /**
     * 扫描包名称
     */
    public static final String SCAN_PACKAGE_NAME = "com.qn";

    private final I18nMsgService i18nMsgService;

    /**
     * 启动后运行
     */
    @PostConstruct
    public void runAfterStartup() {
        log.info("初始化国际化 ErrorCode...");
        // 扫描ErrorCodeConstants类，并获取所有ErrorCode字段
        List<I18nMsg> errorCodeList = scanErrorCodes();
        // 初始化国际化 ErrorCode
        i18nMsgService.init(errorCodeList);
    }

    /**
     * 扫描错误码类，并获取所有ErrorCode字段
     *
     * @return 错误码列表
     */
    private List<I18nMsg> scanErrorCodes() {
        // 根据包名扫描所有枚举类，并获取所有ErrorCode字段
        Set<Class<?>> classes = ClassUtil.scanPackage(InitI18nMsgStartupRunner.SCAN_PACKAGE_NAME, (clazz) -> CollUtil.contains(Arrays.asList(ERROR_CODE_CLASS_NAMES), clazz.getSimpleName()));
        List<I18nMsg> errorCodeList = new ArrayList<>();
        for (Class<?> clazz : classes) {
            Field[] fields = ReflectUtil.getFields(clazz);
            for (Field field : fields) {
                // 判断字段类型是否为ErrorCode
                if (field.getType() == ErrorCode.class) {
                    ErrorCode errorCode = (ErrorCode) ReflectUtil.getFieldValue(clazz, field);
                    I18nMsg i18nMsg = new I18nMsg();
                    i18nMsg.setCode(errorCode.getCode());
                    i18nMsg.setMsg(errorCode.getMsg());
                    i18nMsg.setLocale(I18nEnum.ZH_CN.getCode());
                    i18nMsg.setKeyCode(field.getName());
                    errorCodeList.add(i18nMsg);
                }
            }
        }

        // 排序
        errorCodeList.sort(Comparator.comparingInt(I18nMsg::getCode));
        return errorCodeList;
    }

}